package com.jy.modules.cims.component.annotation;

import java.io.Serializable;
import java.lang.reflect.Method;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;

/**
 * @description 缓存控制
 * @version v1.0
 * @author ShengZhoutao
 * @Date 2012-9-27
 */
@Component
@Aspect
public final class CEhcacheAspect {
	private static final String ETERNAL_CACHE = "eternalCache";// 永久缓存
	private static final String TEMP_CACHE = "tempCache";// 临时缓存

	private static Cache tempCache;
	private static Cache eternalCache;

	static {
		if (eternalCache == null) {
			eternalCache = CacheManager.getInstance().getCache(ETERNAL_CACHE);
			
			if(eternalCache == null){
				eternalCache = new Cache(ETERNAL_CACHE, 10000, false, true, 60000, 60000); 
				CacheManager.getInstance().addCache(eternalCache);
			}
		}
		
		if (tempCache == null) {
			tempCache = CacheManager.getInstance().getCache(TEMP_CACHE);
			
			if(tempCache == null){
				tempCache = new Cache(TEMP_CACHE, 10000, true, false, 60, 60); 
				CacheManager.getInstance().addCache(tempCache);
			}
		}
	}

	@Pointcut("@annotation(Ehcache)")
	public void simplePointcut() {
	}

	@AfterReturning(pointcut = "simplePointcut()")
	public void simpleAdvice() {
	}

	/**
	 * 
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("simplePointcut()")
	public Object aroundCalls(final ProceedingJoinPoint joinPoint) throws Throwable {
		String className = joinPoint.getTarget().getClass().toString();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();

		// 试图得到标注的Ehcache类
		Method[] methods = joinPoint.getTarget().getClass().getMethods();
		Ehcache flag = null;
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class<?>[] tmpCs = method.getParameterTypes();
				if (tmpCs.length == arguments.length) {
					flag = method.getAnnotation(Ehcache.class);
					break;
				}
			}
		}

		if (flag == null) {
			return null;
		}

		Object result;
		String cacheKey = getCacheKey(className, methodName, arguments);

		Element element = null;
		if (flag.eternal()) {
			element = eternalCache.get(cacheKey);// 永久缓存
		} else {
			element = tempCache.get(cacheKey);// 临时缓存
		}

		if (element == null) {
			if ((arguments != null) && (arguments.length != 0)) {
				result = joinPoint.proceed(arguments);
			} else {
				result = joinPoint.proceed();
			}

			element = new Element(cacheKey, (Serializable) result);
			if (flag.eternal()) {
				eternalCache.put(element);// 永久缓存
			} else {
				tempCache.put(element);// 临时缓存
			}
		}
		return element == null ? null : element.getValue();
	}

	/**
	 * @description 获得cache key的方法，cache key是Cache中一个Element的唯一标识 cache key包括
	 *              包名+类名+方法名+参数名
	 * 
	 * @param targetName
	 *            包名+类名
	 * @param methodName
	 *            方法名
	 * @param arguments
	 *            参数
	 * @return
	 */
	private String getCacheKey(final String targetName, final String methodName, Object[] arguments) {
		StringBuffer cacheKey = new StringBuffer();
		cacheKey.append(targetName).append(".").append(methodName);
		if ((arguments != null) && (arguments.length != 0)) {
			String jsonString = JSONArray.toJSON(arguments).toString();
			cacheKey.append(".").append(jsonString);
		}

		return cacheKey.toString();
	}
}
